#pragma once
#include<iostream>
#include<assert.h>
#include"Reverseitereator.h"
namespace bit
{
	template<class T>
	struct ListNode
	{
	public:
		ListNode* next;
		ListNode* preve;
		T value;

	};

	template<class T,class Ret,class Ptr>
	class ListIterator
	{
		typedef ListNode<T>* Node;
		typedef ListNode<T> Pnode;
		typedef ListIterator<T, Ret, Ptr> iterator;
	public:
		ListIterator(const Node& value)
		{
			node = value;
		}
		ListIterator(const iterator& value )
		{
			node = value.node;
		}

		ListIterator()
		{

		}
		Ret operator*()const
		{
			return node->value;
		}

		bool operator!=( iterator value)
		{
			return node != value.node;
		}

		bool operator==( iterator value)
		{
			return !(this != value);
		}

		Ptr operator->()const
		{
			return &(operator*());
		}

		iterator& operator++()
		{
			node = node->next;
			return *this;
		}
        
		iterator& operator--()
		{
			node = node->preve;
			return *this;
		}

		int operator+(int value)
		{
			return 2 + value;
		}


		Node node;
	private:
	};




	template<class T>
	class list
	{
		typedef ListNode<T>* Node;
		typedef ListNode<T> Pnode;
		typedef ListIterator<T,T&,T*> iterator;
		typedef ListIterator<T, const T&,const T*> const_iterator;
		typedef Reverse_iterator<iterator, T&,T* > riterator;
		typedef Reverse_iterator<iterator, const T&, const T* > const_riterator;
	public:
		list()
		{
			head = new Pnode;
			head->next =head;
			head->preve = head;
			head->value = T();
			_size = 0;
		}

		list(size_t n,const T& value=T())
			:list()
		{
			size = n;
			while (n--)
			{
				push_back(value);
			}

		}

		list(const list& value)
			:list()
		{
			_size = value._size;
			const_iterator cur = value.begin();
			for (auto& item : value)
			{
				push_back(item);
			}

		}

		~list()
		{
			iterator temp = begin();
			while (temp != end())
			{
				temp=erase(temp);
			}
			delete(head);
			_size = 0;
		}

		riterator rbegin()
		{
			return end();
		}

		const_riterator rbegin()const
		{
			return begin();
		}

		const_riterator rend()const
		{
			return end();
		}

		riterator rend()
		{
			return begin();
		}

		iterator begin()
		{
			return head->next;
		}

		const_iterator begin()const
		{
			return head->next;
		}

		iterator end()
		{
			return head;
		}

		const_iterator end()const
		{
			return head;
		}

		size_t size()
		{
			return _size;
		}

		void push_back(const T& value)
		{
			insert(end(), value);

		}
		void pop_back()
		{
			erase(end());
		}

		void push_front(const T& value)
		{
			insert(begin(), value);
		}

		void pop_front()
		{
			erase(begin());
		}


		iterator insert(iterator position, const T& val)
		{
			Node cur = position.node;
			Node newNode = new Pnode();
			newNode->preve = cur->preve;
			cur->preve->next = newNode;
			newNode->next = cur;
			newNode->value = val;
			cur->preve = newNode;
			_size++;
			return newNode;
		}

		iterator erase(iterator position)
		{
			assert(position != head);
			Node preve = position.node->preve;
			Node next = position.node->next;
			preve->next = next;
			next->preve = preve;
			_size--;
			delete(position.node);
			return next;
		}

		void empty()
		{
			iterator temp = begin();
			while (temp != end())
			{
				temp=erase(temp);
			}
			_size = 0;
		}

		list& swap(list& x)
		{
			std::swap(_size, x._size);
			std::swap(head, x.head);
			return *this;

		}

		list& operator= ( list x)
		{
			return swap(x);
		}
		



	private:
		Node head;
		size_t _size;
	};

}